昨天我們介紹了 table 元件的篩選和排序功能,今天我們繼續來以程式碼介紹一下如何將 nz-table 和 Material CDK 的 拖拽 和 虛擬滾動 結合使用。
同樣的,我們仍然以 stackblitz 線上程式碼 來說明其用法,先建立個 table 示例。
<nz-table [nzData]="listOfData" [nzFrontPagination]="false" [nzShowPagination]="false">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Address</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of listOfData">
<td>{{ data.name }}</td>
<td>{{ data.age }}</td>
<td>{{ data.address }}</td>
</tr>
</tbody>
</nz-table>
@angular/cdk/drag-drop 模組為你提供了一種方便易用、宣告性地建立可拖放介面的方式,它支援自由拖動、在列表中排序、在列表之間轉移條目、動畫、觸控裝置、自定義拖動把手、預覽和佔位符,以及水平列表和軸向鎖定。
我們可以看到,在一些場景下是十分有用的,而 CDK 拖拽使用也非常簡單,只要將 DragDropModule 匯入到要使用拖放功能的 NgModule 中。這樣你就可以把 cdkDrag 指令新增到元素中,讓它們變得可拖動了。當沒有 cdkDropList(宣告包含一組可拖拽的專案) 元素的時候,可拖動元素可以在頁面中自由移動。你可以新增 cdkDropList 元素來約束元素可以被扔在哪裡。
<div class="example-box" cdkDrag>
Drag me around
</div>
按照上面的方法,我們引入 DragDropModule,tbody 加上 cdkDropList 來包含 tr 元素,表示可拖拽專案組,遍歷 tr 元素新增上 cdkDrag,cdk 也提供了一些快捷工具,如 moveItemInArray,我們看一下現在的程式碼(stackblitz 線上程式碼):
<nz-table [nzData]="listOfData" [nzFrontPagination]="false" [nzShowPagination]="false">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Address</th>
</tr>
</thead>
<tbody cdkDropList (cdkDropListDropped)="drop($event)">
<tr *ngFor="let data of listOfData" cdkDrag>
<td>{{ data.name }}</td>
<td>{{ data.age }}</td>
<td>{{ data.address }}</td>
</tr>
</tbody>
</nz-table>
drop(event: CdkDragDrop<string[]>): void {
moveItemInArray(this.listOfData, event.previousIndex, event.currentIndex);
}
現在已經完成了支援拖拽功能的 nz-table,看一下效果:

cdk-virtual-scroll-viewport通過僅僅渲染那些螢幕上可見的條目,來高效的顯示大型列表。在任何瀏覽器中載入數百個元素都會很慢,虛擬滾動可以用一種高效的方式模擬渲染全部條目,方法是讓容器元素的高度與要渲染的元素的總高度相同,然後才渲染檢視中的條目。虛擬滾動不同於無限滾動這樣的策略,它會渲染一定數量的元素,然後在你點選兩端時渲染剩下的元素。
在視口中建立條目 *cdkVirtualFor 替換了cdk-virtual-scroll-viewport中的 *ngFor,它支援與 *ngFor 完全相同的API。
一個最簡的使用方式:
<cdk-virtual-scroll-viewport itemSize="50" class="example-viewport">
<div *cdkVirtualFor="let item of items" class="example-item">{{item}}</div>
</cdk-virtual-scroll-viewport>
stackblitz 線上程式碼,閱讀前請先參考一下 NG-ZORRO 官方文件 關於虛擬滾動相關的 API。
同樣的,大資料量的渲染也是一直困擾使用者體驗的問題,在沒有虛擬滾動之前,我們只能通過分頁等方式來保證每頁顯示數量在瀏覽器可接受範圍內,但是 cdk virtual scrolling 釋出之後,這些問題便得到了極大地改善,NG-ZORRO 也基於此實現了虛擬滾動的相關屬性,這些屬性和 cdk scrolling 的相關屬性一致。
| 引數 | 說明 | 型別 | 預設值 |
|---|---|---|---|
[nzVirtualScroll] |
是否啟用虛擬滾動模式,與 [nzScroll] 配合使用 |
boolean |
false |
[nzVirtualItemSize] |
虛擬滾動時每一列的高度,與 cdk itemSize 相同 | number |
0 |
[nzVirtualMaxBufferPx] |
緩衝區最大畫素高度,與 cdk maxBufferPx 相同 | number |
200 |
[nzVirtualMinBufferPx] |
緩衝區最小畫素高度,低於該值時將載入新結構,與 cdk minBufferPx 相同 | number |
100 |
[nzVirtualForTrackBy] |
虛擬滾動資料 TrackByFunction 函式 |
TrackByFunction<T> |
- |
我們先準備大量的資料,來用於模擬渲染
const data = [];
for (let i = 0; i < 20000; i++) {
data.push({
key: i,
name: `Edward King`,
age: 32,
address: `London`
});
}
安裝官方文件說明,我們來改造一下 na-table,現在的 table 變成了這樣:
<nz-table
#virtualTable
nzVirtualScroll
[nzVirtualItemSize]="54"
[nzData]="listOfData"
[nzVirtualForTrackBy]="trackByIndex"
[nzFrontPagination]="false"
[nzShowPagination]="false"
[nzScroll]="{ x: '700px', y: '240px' }"
>
<thead>
<tr>
<th nzWidth="100px">Index</th>
<th nzWidth="200px">Name</th>
<th nzWidth="200px">Age</th>
<th nzWidth="200px">Address</th>
</tr>
</thead>
<tbody>
<ng-template nz-virtual-scroll let-data let-index="index">
<tr>
<td>{{data.key}}</td>
<td>{{ data.name }}</td>
<td>{{ data.age }}</td>
<td>{{ data.address }}</td>
</tr>
</ng-template>
</tbody>
</nz-table>

通過兩個例子,我們瞭解瞭如何將 nz-table 和 Material CDK 結合使用,NG-ZORRO 的其他元件也能夠很好地和 CDK 結合,比如 nz-list 等等。一般我們並不用擔心 NG-ZORRO 的元件和 Material CDK 的相容性,當然,如果你發現有相容性不好的情況,也可以參與社群建設,為 NG-ZORRO 提 Issue 或者 Pull Request 來一起完善元件庫。